﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Cinchoo.Core;
using ChoWorkflowServer.Model;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Interop;
using System.Globalization;
using System.Collections;
using System.Windows.Controls.Primitives;
using Cinchoo.Core.Diagnostics;
using Cinchoo.Core.WPF;
using Cinchoo.Core.Windows.Forms;
using System.Reflection;
using Cinchoo.Core.Reflection;
using System.IO;

namespace ChoWorkflowDashboard
{
    /// <summary>
    /// Interaction logic for AddOrEditTaskWindow.xaml
    /// </summary>
    public partial class AddOrEditTaskWindow : ChoBaseWindowEx
    {
        private readonly IChoDataModel _dataModel = ChoDataModelFactory.New();
        private string _taskGroupName = null;
        private string _taskName = null;
        private readonly bool _isEditMode = false;
        private bool _canAutoEditWorkflowName = true;
        private ChoTaskGroupCategory capturedObj;

        private bool _isDataUpdated;
        internal bool IsDataUpdated
        {
            get { return _isDataUpdated; }
            set
            {
                if (value)
                    _isDataUpdated = value;
            }
        }

        public ChoTaskGroupCategory TaskGroupCategoryInfo
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_TASK_SCHEDULESDataTable TaskSchedulesTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_HOLIDAY_CALENDARSDataTable TaskHolidayCalTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_SCHEDULE_TYPESDataTable TaskScheduleTypesTable
        {
            get;
            set;
        }

        private List<string> _machines = new List<string>();
        public List<string> Machines
        {
            get { return _machines; }
            private set
            {
                if (value != null)
                {
                    _machines.Clear();
                    _machines.AddRange(value);
                }
            }
        }

        private List<string> _wfNames = new List<string>();
        public List<string> WFNames
        {
            get { return _wfNames; }
            private set
            {
                if (value != null)
                {
                    _wfNames.Clear();
                    _wfNames.AddRange(value);
                }
            }
        }

        public IEnumerable<YearMonth> YearMonths { get; set; }

        public YearMonth SelectedYearMonth
        {
            get { return (YearMonth)GetValue(SelectedYearMonthProperty); }
            set { SetValue(SelectedYearMonthProperty, value); }
        }

        public static readonly DependencyProperty SelectedYearMonthProperty =
            DependencyProperty.Register("SelectedYearMonth",
                                        typeof(YearMonth),
                                        typeof(AddOrEditTaskWindow),
                                        new UIPropertyMetadata(null));

        private CollectionViewSource _checkedYearMonths;

        private IList _monthWeeks;
        public IList MonthWeeks
        {
            get
            {
                if (_monthWeeks == null)
                {
                    _monthWeeks = new List<Tuple<int, string>>(ChoEnum.ToEnumPairValues<ChoWeekOfMonth>());
                    ListCollectionView view = CollectionViewSource.GetDefaultView(_monthWeeks) as ListCollectionView;
                    view.CustomSort = new TupleSorter();
                }

                return _monthWeeks;
            }
        }

        public ChoWeekOfMonth SelectedMonthWeek
        {
            get { return (ChoWeekOfMonth)GetValue(SelectedMonthWeekProperty); }
            set { SetValue(SelectedMonthWeekProperty, value); }
        }

        public static readonly DependencyProperty SelectedMonthWeekProperty =
            DependencyProperty.Register("SelectedMonthWeek",
                                        typeof(ChoWeekOfMonth),
                                        typeof(AddOrEditTaskWindow),
                                        new UIPropertyMetadata(null));

        private IList _dayOfWeeks;
        public IList DayOfWeeks
        {
            get
            {
                if (_dayOfWeeks == null)
                {
                    _dayOfWeeks = new List<Tuple<int, string>>(ChoEnum.ToEnumPairValues<DayOfWeek>());
                    ListCollectionView view = CollectionViewSource.GetDefaultView(_dayOfWeeks) as ListCollectionView;
                    view.CustomSort = new TupleSorter();
                }

                return _dayOfWeeks;
            }
        }

        public DayOfWeek SelectedWeekDay
        {
            get { return (DayOfWeek)GetValue(SelectedMonthWeekProperty); }
            set { SetValue(SelectedMonthWeekProperty, value); }
        }

        public static readonly DependencyProperty SelectedWeekDayProperty =
            DependencyProperty.Register("SelectedWeekDay",
                                        typeof(DayOfWeek),
                                        typeof(AddOrEditTaskWindow),
                                        new UIPropertyMetadata(null));

        private IList _repeatIntervalTypes;
        public IList RepeatIntervalTypes
        {
            get
            {
                if (_repeatIntervalTypes == null)
                {
                    _repeatIntervalTypes = new List<Tuple<int, string>>(ChoEnum.ToEnumPairValues<ChoRepeatIntervalType>());
                    ListCollectionView view = CollectionViewSource.GetDefaultView(_repeatIntervalTypes) as ListCollectionView;
                    view.CustomSort = new TupleSorter();
                }

                return _repeatIntervalTypes;
            }
        }

        public AddOrEditTaskWindow(ChoTaskGroupCategory taskGroupCategory, string[] machines, string[] wfNames, bool isEditMode = false)
        {
            ChoGuard.ArgumentNotNullOrEmpty(taskGroupCategory, "taskGroupCategory");

            using (new ChoWaitCursor())
            {
                _isEditMode = isEditMode;

                _taskName = taskGroupCategory.Name;
                Machines = new List<string>(machines);
                WFNames = new List<string>(wfNames);
                TaskGroupCategoryInfo = taskGroupCategory;
                if (TaskGroupCategoryInfo.Parent == null
                    || TaskGroupCategoryInfo.Parent.Name.IsNullOrWhiteSpace())
                    throw new ArgumentException("Missing task group name.");

                _taskGroupName = TaskGroupCategoryInfo.Parent.Name;
                _canAutoEditWorkflowName = TaskGroupCategoryInfo.WorkflowName.IsNullOrEmpty();
                TaskSchedulesTable = _dataModel.GetTaskSchedules(taskGroupCategory._id, null);
                if (!_isEditMode)
                    AddNewSchedule("S1");

                DataColumn auditInfoColumn = new DataColumn();
                auditInfoColumn.DataType = System.Type.GetType("System.String");
                auditInfoColumn.ColumnName = "AUDIT_INFO";
                auditInfoColumn.Expression = "'Created By: ' + CREATED_BY + '\nCreated Date: ' + CREATED_DATE + '\nModified By: ' + MODIFIED_BY + '\nModified Date: ' + MODIFIED_DATE";

                TaskSchedulesTable.Columns.Add(auditInfoColumn);

                TaskHolidayCalTable = _dataModel.GetAllHolidayCalendars();
                TaskHolidayCalTable.DefaultView.Sort = TaskHolidayCalTable.CAL_IDColumn.ColumnName;

                TaskScheduleTypesTable = _dataModel.GetTaskScheduleTypes();

                InitializeComponent();

                dpStartDate.DisplayDateStart = DateTime.Today;

                List<YearMonth> yearMonths = new List<YearMonth>();
                foreach (ChoMonthOfYear monthOfYear in System.Enum.GetValues(typeof(ChoMonthOfYear)))
                {
                    yearMonths.Add(new YearMonth() { MonthOfYear = monthOfYear });
                }

                YearMonths = yearMonths;

                _checkedYearMonths = FindResource("checkedMonths") as CollectionViewSource;

                List<ChoWeekOfMonth> monthWeeks = new List<ChoWeekOfMonth>();
                foreach (ChoWeekOfMonth weekOfMonth in System.Enum.GetValues(typeof(ChoWeekOfMonth)))
                {
                    monthWeeks.Add(weekOfMonth);
                }

                //MonthWeeks = monthWeeks;

                List<DayOfWeek> dayOfWeeks = new List<DayOfWeek>();
                foreach (DayOfWeek dayOfWeek in System.Enum.GetValues(typeof(DayOfWeek)))
                {
                    dayOfWeeks.Add(dayOfWeek);
                }

                //DayOfWeeks = dayOfWeeks;

                this.DataContext = this;

                ComponentDispatcher.ThreadIdle += new EventHandler(ComponentDispatcher_ThreadIdle);
                //txtTaskName.IsEnabled = !_isEditMode;
            }
        }

        public AddOrEditTaskWindow()
        {
        }

        private void ChoBaseWindow_Loaded(object sender, RoutedEventArgs e)
        {
            capturedObj = TaskGroupCategoryInfo.Capture();
            if (!_isEditMode)
                TaskGroupCategoryInfo.IsDirty = false;
        }

        void ComponentDispatcher_ThreadIdle(object sender, EventArgs e)
        {
            btnDeleteSchedule.IsEnabled = lstSchedules.SelectedIndex >= 0;
            chkEnabled.IsEnabled = lstSchedules.SelectedIndex >= 0;
            grpHolidayCal.IsEnabled = lstSchedules.SelectedIndex >= 0;
            grpScheduleDetails.IsEnabled = lstSchedules.SelectedIndex >= 0;
            btnNewSchedule.IsEnabled = txtScheduleName.Text.Length > 0;
        }

        protected override bool UpdateChanges()
        {
            bool ret = UpdateTask();
            if (ret)
                TaskSchedulesTable.AcceptChanges();

            return ret;
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            _promptSaveChanges = false;
            this.DialogResult = true;
            //this.Close();
        }

        protected override bool HasChanges
        {
            get
            {
                DataTable table = null;
                bool hasChanges = false;

                if (!hasChanges)
                {
                    if (TaskGroupCategoryInfo != null && TaskGroupCategoryInfo.IsDirty)
                        hasChanges = true;
                }

                if (!hasChanges)
                {
                    table = TaskSchedulesTable != null ? TaskSchedulesTable.GetChanges() : null;
                    hasChanges = table != null && table.Rows.Count > 0;
                }

                IsDataUpdated = hasChanges;
                return hasChanges;
            }
        }

        private bool UpdateTask()
        {
            if (TaskGroupCategoryInfo.Name.IsNullOrWhiteSpace())
            {
                MessageBox.Show("Enter valid task name.", Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            try
            {
                if (!_isEditMode)
                    ChoMainWindow.CheckMaxNoOfAllowdTasksReached();

                //Check for duplicate task name.
                if (_dataModel.IsTaskExists(TaskGroupCategoryInfo.Name))
                {
                    if (_taskName != TaskGroupCategoryInfo.Name)
                    {
                        MessageBox.Show("Duplicate task found.", Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);
                        return false;
                    }
                }

                ChoTasksDataSet.CHO_TASK_SCHEDULESDataTable changes = TaskSchedulesTable.GetChanges() as ChoTasksDataSet.CHO_TASK_SCHEDULESDataTable;

                //Check for duplicate task name.
                if (_dataModel.AddOrUpdateTask(TaskGroupCategoryInfo.Name, TaskGroupCategoryInfo.WorkflowName, TaskGroupCategoryInfo.Description,
                    TaskGroupCategoryInfo.Parent.Id, TaskGroupCategoryInfo.CmdParameters, TaskGroupCategoryInfo.MaxNoOfRetry, TaskGroupCategoryInfo.SleepBetweenRetry,
                    TaskGroupCategoryInfo.Timeout, TaskGroupCategoryInfo.MachineName, changes, ChoUser.CurrentUser, Environment.MachineName) <= 0)
                {
                    MessageBox.Show("Failed to add task.", Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);
                    return false;
                }

                //if (!UpdateScheduleInfo())
                //    return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while adding task.{0}{1}.".FormatString(Environment.NewLine, ex.Message),
                    Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }
            return true;
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
        }

        private void lstSchedules_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            //if (e.RemovedItems.Count == 0)
            //    return;

            //ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = ((DataRowView)e.RemovedItems[0]).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow;
            //if (row == null) return;

            //if (row.RowState == DataRowState.Unchanged)
            //    return;

            //if (!UpdateChanges(row))
            //{
            //    lstSchedules.SelectedItem = e.RemovedItems[0];
            //    return;
            //}

            //TaskSchedulesTable.AcceptChanges();
            //e.Handled = true;
        }

        private void btnNewSchedule_Click(object sender, RoutedEventArgs e)
        {
            if (txtScheduleName.Text.Trim().Length == 0) return;

            var x = (from row1 in TaskSchedulesTable.AsEnumerable<ChoTasksDataSet.CHO_TASK_SCHEDULESRow>()
                     where row1[TaskSchedulesTable.SCHEDULE_NAMEColumn, DataRowVersion.Original] != DBNull.Value
                    && (string)row1[TaskSchedulesTable.SCHEDULE_NAMEColumn, DataRowVersion.Original] == txtScheduleName.Text
                     select row1).FirstOrDefault();
            if (x != null) return;

            AddNewSchedule(txtScheduleName.Text.Trim());

            txtScheduleName.Text = String.Empty;

            //if (!UpdateChanges(row))
            //{
            //    return;
            //}

            //TaskSchedulesTable.AcceptChanges();
            lstSchedules.SelectedIndex = lstSchedules.Items.Count - 1;
            BindingOperations.GetBindingExpression(cmbHolidayCal, ComboBox.SelectedValueProperty).UpdateTarget();
            e.Handled = true;
        }

        private void AddNewSchedule(string scheduleName, bool acceptChanges = false)
        {
            ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = TaskSchedulesTable.NewCHO_TASK_SCHEDULESRow();
            row.SCHEDULE_ID = -1;
            row.HOLIDAY_CAL_ID = ChoCalendar.NULL_CALENDAR_ID;
            row.HOLIDAY_CAL_NAME = ChoCalendar.NULL_CALENDAR_NAME;
            row.SCHEDULE_NAME = scheduleName;
            row.TASK_ID = TaskGroupCategoryInfo._id;
            row.ENABLED = true;
            row.START_DATE = DateTime.Today;
            row.START_TIME = DateTime.MinValue;
            row.SUN = false;
            row.MON = false;
            row.TUE = false;
            row.WED = false;
            row.THU = false;
            row.FRI = false;
            row.SAT = false;
            row.REPEAT_ENABLED = false;
            row.SCHEDULE_TYPE_ID = 1;
            row.DAILY_EVERY_DAYS = 1;
            row.WEEKLY_EVERY_WEEKS = 1;
            row.MONTHLY_DAY_OF_MONTH = true;
            row.FIRE_AFTER_DEPENDENCY = 0;
            row.REPEAT_INTERVAL = 1;
            row.REPEAT_INTERVAL_TYPE = 0;
            row.CREATED_BY = ChoUser.CurrentUser;
            row.CREATED_DATE = DateTime.Now;
            row.MODIFIED_BY = ChoUser.CurrentUser;
            row.MODIFIED_DATE = DateTime.Now;
            TaskSchedulesTable.AddCHO_TASK_SCHEDULESRow(row);

            if (acceptChanges)
                TaskSchedulesTable.AcceptChanges();
        }

        private void btnDeleteSchedule_Click(object sender, RoutedEventArgs e)
        {
            object selectedItem = lstSchedules.SelectedItem;
            if (selectedItem == null) return;
            ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = ((DataRowView)selectedItem).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow;
            if (row == null) return;

            if (MessageBox.Show("Are you sure you want to delete the '{0}' schedule?".FormatString(row.SCHEDULE_NAME), Application.Current.MainWindow.Title,
                MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
                return;

            //if (!UpdateChanges(row))
            //    return;

            //TaskSchedulesTable.Rows.Remove(row);
            row.Delete();
            //TaskSchedulesTable.AcceptChanges();
            e.Handled = true;
        }

        private void chkMonthName_Click(object sender, RoutedEventArgs e)
        {
            _checkedYearMonths.View.Refresh();
        }

        private void IsCheckedFilter(object sender, FilterEventArgs e)
        {
            YearMonth yearMonth = e.Item as YearMonth;
            e.Accepted = yearMonth.IsChecked;
        }

        private void dpStartDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {
            dpEndDate.DisplayDateStart = dpStartDate.SelectedDate;
            if (dpStartDate.SelectedDate > dpEndDate.SelectedDate)
            {
                dpEndDate.SelectedDate = null;
            }
        }

        private void dpEndDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void dtStartTime_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (dtStartTime.Value >= dtEndTime.Value)
            {
                dtEndTime.Value = null;
            }
        }

        private void dtEndTime_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            //if (dtEndTime.Value == null)
            //    dtEndTime.Value = dtStartTime.Value.Value.AddMinutes(1);
            if (dtStartTime.Value >= dtEndTime.Value)
            {
                dtEndTime.Value = null;
            }
        }

        private void dpStartDate_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void dpEndDate_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void cmbScheduleTask_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            object selectedItem = lstSchedules.SelectedItem;
            if (selectedItem == null) return;
            ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = ((DataRowView)selectedItem).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow;
            if (row == null) return;

            if (!row.IsSCHEDULE_TYPE_IDNull() && row.SCHEDULE_TYPE_ID == 4)
            {
                row.REPEAT_ENABLED = false;
                try
                {
                    BindingOperations.GetBindingExpression(chkRepeat, CheckBox.IsCheckedProperty).UpdateTarget();
                    BindingOperations.GetBindingExpression(cvsRepeat, Canvas.IsEnabledProperty).UpdateTarget();
                }
                catch (Exception)
                {
                }
                chkRepeat.IsEnabled = false;
            }
            else
                chkRepeat.IsEnabled = true;
        }

        private void cmbHolidayCal_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            dpStartDate.BlackoutDates.Clear();
            dpEndDate.BlackoutDates.Clear();
            if (e.AddedItems == null || e.AddedItems.Count == 0) return;

            ChoTasksDataSet.CHO_HOLIDAY_CALENDARSRow row1 = ((DataRowView)e.AddedItems[0]).Row as ChoTasksDataSet.CHO_HOLIDAY_CALENDARSRow;
            if (row1 == null) return;

            ChoTasksDataSet.CHO_HOLIDAY_CALENDAR_DATESDataTable table = _dataModel.GetAllHolidayCalendarDatesByName(row1.CAL_NAME);
            foreach (ChoTasksDataSet.CHO_HOLIDAY_CALENDAR_DATESRow row in table)
            {
                try
                {
                    dpStartDate.BlackoutDates.Add(new CalendarDateRange(row.CAL_DATE));
                }
                catch { }

                try
                {
                    dpEndDate.BlackoutDates.Add(new CalendarDateRange(row.CAL_DATE));
                }
                catch { }
            }
        }

        private void txtScheduleDesc_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ChoMultilineInputWindow multilineInputWindow = new ChoMultilineInputWindow(txtScheduleDesc.Text, "Please enter task comments");
            ChildWindow = multilineInputWindow;
            bool? retValue = multilineInputWindow.ShowDialog();
            if (retValue == null || !retValue.Value)
                return;

            txtScheduleDesc.Text = multilineInputWindow.InputText;
        }

        private void txtDependencies_Click(object sender, RoutedEventArgs e)
        {
            if (lstSchedules.SelectedItem == null) return;

            ChoTaskDependencyWindow window = new ChoTaskDependencyWindow(txtTaskName.Text, ((DataRowView)lstSchedules.SelectedItem).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow, 
                "Please enter task dependencies");

            ChildWindow = window;
            bool? retValue = window.ShowDialog();
            BindingOperations.GetBindingExpression(btnDependencies, Button.BackgroundProperty).UpdateTarget();

            if (retValue == null || !retValue.Value)
                return;
        }

        //private void btnComments_Click(object sender, RoutedEventArgs e)
        //{
        //    ChoMultilineInputWindow multilineInputWindow = new ChoMultilineInputWindow(btnComments.Tag.ToString(), "Please enter task comments");
        //    ChildWindow = multilineInputWindow;
        //    bool? retValue = multilineInputWindow.ShowDialog();
        //    if (retValue == null || !retValue.Value)
        //        return;

        //    TaskGroupCategoryInfo.Description = multilineInputWindow.InputText;
        //}

        private void txtCmdParams_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //ChoTaskCmdParamsEditor wnd1 = new ChoTaskCmdParamsEditor(TaskGroupCategoryInfo.WorkflowName, TaskGroupCategoryInfo.CmdParameters);
            //wnd1.ShowDialog();
            //return;
            try
            {
                AppDomainSetup appDomainSetup = new AppDomainSetup() { ShadowCopyFiles = "true" };
                appDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                ChoAssemblyResolver resolver = new ChoAssemblyResolver();
                var domain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), AppDomain.CurrentDomain.Evidence, appDomainSetup);
                resolver.Attach(domain);
                domain.SetData("wfName", TaskGroupCategoryInfo.WorkflowName);
                domain.SetData("cmdParams", TaskGroupCategoryInfo.CmdParameters);

                domain.DoCallBack(() =>
                {
                    ChoFramework.Initialize();
                    App app = new App();
                    app.InitializeComponent();
                    ChoTaskCmdParamsEditor wnd = new ChoTaskCmdParamsEditor(AppDomain.CurrentDomain.GetData("wfName") as string,
                        AppDomain.CurrentDomain.GetData("cmdParams") as string);

                    app.MainWindow = wnd;
                    app.MainWindow.ShowDialog();
                    AppDomain.CurrentDomain.SetData("cmdParams", wnd.CmdParams);

                    app.Run();
                });

                string cmdParams = domain.GetData("cmdParams") as string;
                if (!cmdParams.IsNull())
                    txtCmdParams.Text = cmdParams;

                AppDomain.Unload(domain);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error opening Command Param Editor. {0}{1}. {0}{0}Opening default editor...".FormatString(Environment.NewLine, ex.Message), Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);

                ChoMultilineInputWindow inputWindow = new ChoMultilineInputWindow(txtCmdParams.Text, "Please enter command params");
                ChildWindow = inputWindow;
                bool? retValue = inputWindow.ShowDialog();
                if (retValue == null || !retValue.Value)
                    return;

                txtCmdParams.Text = inputWindow.InputText;
            }
            finally
            {
            }
        }

        private void txtComments_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ChoMultilineInputWindow multilineInputWindow = new ChoMultilineInputWindow(txtComments.Text, "Please enter task comments");
            ChildWindow = multilineInputWindow;
            bool? retValue = multilineInputWindow.ShowDialog();
            if (retValue == null || !retValue.Value)
                return;

            TaskGroupCategoryInfo.Description = multilineInputWindow.InputText;
        }

        protected override void RejectChanges()
        {
            TaskGroupCategoryInfo.Undo(capturedObj);
            TaskSchedulesTable.RejectChanges();
        }

        private void btnChooseCluster_Click(object sender, RoutedEventArgs e)
        {
            ChoClusterNodesViewer wnd = new ChoClusterNodesViewer();
            bool? retValue = wnd.ShowDialog();
            if (retValue == null || !retValue.Value)
                return;

            if (!wnd.SelectedClusterOrNode.IsNullOrWhiteSpace())
                cmbMachineName.SelectedValue = wnd.SelectedClusterOrNode;
        }

        private void btnEditCmdParams_Click(object sender, RoutedEventArgs e)
        {
            txtCmdParams_MouseDoubleClick(sender, null);
        }

        private void btnEndTImeReset_Click(object sender, RoutedEventArgs e)
        {
            dtEndTime.Value = null;

            object selectedItem = lstSchedules.SelectedItem;
            if (selectedItem == null) return;
            ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = ((DataRowView)selectedItem).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow;
            if (row == null) return;

            row.SetEND_TIMENull();
        }

        private void btnEndDateReset_Click(object sender, RoutedEventArgs e)
        {
            dpEndDate.SelectedDate = null;
            object selectedItem = lstSchedules.SelectedItem;
            if (selectedItem == null) return;
            ChoTasksDataSet.CHO_TASK_SCHEDULESRow row = ((DataRowView)selectedItem).Row as ChoTasksDataSet.CHO_TASK_SCHEDULESRow;
            if (row == null) return;

            row.SetEND_DATENull();
        }

        private void cmbWorkflowName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            txtCmdParams.Text = String.Empty;
        }

        //private void txtTaskName_TextChanged(object sender, TextChangedEventArgs e)
        //{
        //    if (_canAutoEditWorkflowName)
        //    {
        //        txtWorkflowName.Text = txtTaskName.Text;
        //        BindingOperations.GetBindingExpression(txtWorkflowName, TextBox.TextProperty).UpdateSource();
        //    }
        //}

        //private void txtWorkflowName_GotFocus(object sender, RoutedEventArgs e)
        //{
        //    _canAutoEditWorkflowName = false;
        //}

    }

    public class YearMonth
    {
        public ChoMonthOfYear MonthOfYear { get; set; }
        public bool IsChecked { get; set; }
    }

    public class MonthSelectedConverter : IValueConverter
    {
        private string _state;

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is string) || !(parameter is int)) return false;
            int parameterValue = (int)parameter;
            string valueText = value as string;

            _state = valueText;
            if (valueText.IsNullOrWhiteSpace()) return false;
            return valueText.Substring(parameterValue - 1, 1) == "1";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (_state.IsNullOrWhiteSpace()) return null;

            if (!(value is bool) || !(parameter is int)) return null;
            int parameterValue = (int)parameter;
            bool isChecked = (bool)value;

            _state = _state.ReplaceAt(parameterValue - 1, isChecked ? '1' : '0');
            return _state;
        }
    }

    public class TimeSpanDateTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is TimeSpan)) return false;
            TimeSpan ts = (TimeSpan)value;
            return new DateTime().Add(TimeSpan.FromMilliseconds(ts.TotalMilliseconds));
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is DateTime)) return false;
            DateTime dt = (DateTime)value;
            return dt.TimeOfDay;
        }
    }

    internal class DateConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string date = ((DateTime)value).ToShortDateString();
            if (!date.Equals("1/1/1753") && !date.Equals("1/1/0001"))
                return ((DateTime)value).ToShortDateString();
            return String.Empty;
        }
        /// <summary>
        /// method for convert back
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string strValue = value == null ? string.Empty : value.ToString();
            DateTime resultDateTime;
            if (!string.IsNullOrEmpty(strValue))
                return DateTime.TryParse(strValue, out resultDateTime) ? resultDateTime : value;
            else
                return ChoDbDateTime.MinValue;
        }
    }

    public class ObjectValueToBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value != null;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }

    public class ExtendedDatePicker : DatePicker
    {
        public static readonly DependencyProperty EditableProperty = DependencyProperty.Register("Editable", typeof(bool),
            typeof(ExtendedDatePicker), new PropertyMetadata(true));
        public bool Editable
        {
            get { return (bool)GetValue(EditableProperty); }
            set { SetValue(EditableProperty, value); }
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var textBox = GetTemplateChild("PART_TextBox") as System.Windows.Controls.Primitives.DatePickerTextBox;
            var binding = new Binding { Source = this, Path = new PropertyPath(ExtendedDatePicker.EditableProperty) };
            textBox.SetBinding(System.Windows.Controls.Primitives.DatePickerTextBox.FocusableProperty, binding);
        }
    }

    public class DependencyBackgroudColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.IsNullOrDbNull() || (value is string && ((string)value).IsNullOrWhiteSpace()))
                return Brushes.LightGray;
            else
                return Brushes.LightGreen;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }

    public class DependencyExistsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.IsNullOrDbNull() || (value is string && ((string)value).IsNullOrWhiteSpace()))
                return true;
            else
                return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }

    public class TupleSorter : IComparer
    {
        #region IComparer Members

        public int Compare(object x, object y)
        {
            // implement your sort algorithm here 
            // the following is just a sample which sorts based on the lenght of the value of the Name property

            Tuple<int, string> obj1 = x as Tuple<int, string>;
            Tuple<int, string> obj2 = y as Tuple<int, string>;
            return obj1.Item1 - obj2.Item1;
        }

        #endregion
    }
}
